<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="eddbA" id="eddbA"><span data-lake-id="u9670a05d" id="u9670a05d">典型回答</span></h1>
  <p data-lake-id="u97b34348" id="u97b34348"><br></p>
  <p data-lake-id="ud7c360ef" id="ud7c360ef"><span data-lake-id="u2be26c82" id="u2be26c82">我们知道，ConcurrentHashMap在使用时，和HashMap有一个比较大的区别，</span><strong><span data-lake-id="ue0320adf" id="ue0320adf">那就是HashMap中，null可以作为键或者值都可以。而在ConcurrentHashMap中，key和value都不允许为null。</span></strong></p>
  <p data-lake-id="ub5110322" id="ub5110322"><strong><span data-lake-id="uce59137f" id="uce59137f">​</span></strong><br></p>
  <p data-lake-id="u641a683d" id="u641a683d"><span data-lake-id="u71e8857d" id="u71e8857d">那么，为什么呢？为啥ConcurrentHashMap要设计成这样的呢？</span></p>
  <p data-lake-id="u34f8160f" id="u34f8160f"><span data-lake-id="ua809b1ad" id="ua809b1ad">​</span><br></p>
  <p data-lake-id="u78f0c90c" id="u78f0c90c"><span data-lake-id="u05c95611" id="u05c95611">关于这个问题，其实最有发言权的就是ConcurrentHashMap的作者——Doug Lea&#x0;</span></p>
  <p data-lake-id="u5c075572" id="u5c075572"><span data-lake-id="uaca2b054" id="uaca2b054">​</span><br></p>
  <p data-lake-id="ud803648b" id="ud803648b"><span data-lake-id="ub4206fd3" id="ub4206fd3">他自己曾经出面解释过这个问题，内容如下（</span><a href="http://cs.oswego.edu/pipermail/concurrency-interest/2006-May/002485.html" target="_blank" data-lake-id="uc9ab8e91" id="uc9ab8e91"><span data-lake-id="ua0014a9c" id="ua0014a9c">http://cs.oswego.edu/pipermail/concurrency-interest/2006-May/002485.html</span></a><span data-lake-id="ud2f95412" id="ud2f95412"> ，原文地址已经打不开了，大家将就着看一下截图吧） ：</span></p>
  <p data-lake-id="u5d67702e" id="u5d67702e"><span data-lake-id="u75d9e1d2" id="u75d9e1d2">​</span><br></p>
  <p data-lake-id="u2f1bea84" id="u2f1bea84"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1682668637012-43a0139c-7ec8-4813-a37a-4a710d187b08.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_16%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u510caf42" id="u510caf42"><span data-lake-id="ue0c3a1d3" id="ue0c3a1d3">​</span><br></p>
  <p data-lake-id="u635f3155" id="u635f3155"><span data-lake-id="u653cdda2" id="u653cdda2">​</span><br></p>
  <p data-lake-id="u9fc290fe" id="u9fc290fe"><strong><span data-lake-id="uf624cac3" id="uf624cac3">主要意思就是说：</span></strong></p>
  <p data-lake-id="uf49764f0" id="uf49764f0"><span data-lake-id="uc0dfd434" id="uc0dfd434">​</span><br></p>
  <p data-lake-id="u5482c012" id="u5482c012"><span data-lake-id="u2d39c964" id="u2d39c964">ConcurrentMap（如ConcurrentHashMap、ConcurrentSkipListMap）不允许使用null值的主要原因是，</span><strong><span data-lake-id="u729f50ef" id="u729f50ef">在非并发的Map中（如HashMap)，是可以容忍模糊性（二义性）的，而在并发Map中是无法容忍的。</span></strong></p>
  <p data-lake-id="uef8c4491" id="uef8c4491"><span data-lake-id="u53988a3b" id="u53988a3b">​</span><br></p>
  <p data-lake-id="ueb66e710" id="ueb66e710"><span data-lake-id="ub0e47a41" id="ub0e47a41">假如说，所有的Map都支持null的话，那么map.get(key)就可以返回null，但是，这时候就会存在一个不确定性，当你拿到null的时候，你是不知道他是因为本来就存了一个null进去还是说就是因为没找到而返回了null。</span></p>
  <p data-lake-id="ud38a74c2" id="ud38a74c2"><br></p>
  <p data-lake-id="u64111839" id="u64111839"><span data-lake-id="u0e50cd6b" id="u0e50cd6b">在HashMap中，因为它的设计就是给单线程用的，所以当我们map.get(key)返回null的时候，我们是可以通过map.contains(key)检查来进行检测的，如果它返回true，则认为是存了一个null，否则就是因为没找到而返回了null。</span></p>
  <p data-lake-id="u262f90e0" id="u262f90e0"><span data-lake-id="ucd2aea24" id="ucd2aea24">​</span><br></p>
  <p data-lake-id="u8bf6f483" id="u8bf6f483"><span data-lake-id="ufe804866" id="ufe804866">但是，像ConcurrentHashMap，它是为并发而生的，它是要用在并发场景中的，当我们map.get(key)返回null的时候，是没办法通过map.contains(key)检查来准确的检测，因为在检测过程中可能会被其他线程所修改，而导致检测结果并不可靠。</span></p>
  <p data-lake-id="ue21ac927" id="ue21ac927"><br></p>
  <p data-lake-id="u62f1260c" id="u62f1260c"><span data-lake-id="u9305fd2f" id="u9305fd2f">所以，为了让ConcurrentHashMap的语义更加准确，不存在二义性的问题，他就不支持null。</span></p>
 </body>
</html>